package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.CacheOperationType;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.cache.GuiGuCached;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 保存专辑信息，涉及三张表 AlbumInfo、AlbumAttributeValue、AlbumStat
     * 判断用户专辑的状态，自动上架专辑信息， rabbitService 发送消息
     *
     * @param userId
     * @param albumInfoVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(Long userId, AlbumInfoVo albumInfoVo) {
        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtil.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setUserId(userId);
        albumInfo.setIncludeTrackCount(0);
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        albumInfoMapper.insert(albumInfo);
        Long albumId = albumInfo.getId();
        for (AlbumAttributeValueVo albumAttributeValueVo : albumInfoVo.getAlbumAttributeValueVoList()) {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumId);
            albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
            albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
            albumAttributeValueMapper.insert(albumAttributeValue);
        }

        this.saveAlbumStat(albumId, SystemConstant.ALBUM_STAT_PLAY, 10);
        this.saveAlbumStat(albumId, SystemConstant.ALBUM_STAT_SUBSCRIBE, 10);
        this.saveAlbumStat(albumId, SystemConstant.ALBUM_STAT_BUY, 10);
        this.saveAlbumStat(albumId, SystemConstant.ALBUM_STAT_COMMENT, 10);

        // 发送消息至 search 服务
        if (albumInfo.getIsOpen().equals("1")) {
            // 1 == 公开状态即上架专辑
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumId);
        }
    }

    @Override
    public void saveAlbumStat(Long albumId, String statType, Integer statNum) {
        AlbumStat albumStat = new AlbumStat();
        albumStat.setAlbumId(albumId);
        albumStat.setStatType(statType);
        albumStat.setStatNum(statNum);
        albumStatMapper.insert(albumStat);
    }

    @Override
    public Page<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
        return albumInfoMapper.findUserAlbumPage(albumListVoPage, albumInfoQuery);

    }

    /***
     * 根据专辑ID查询专辑信息包含专辑标签列表
     * @param id 专辑 albumId
     * @return
     */
    @Override
    //@GuiGuCache(prefix = "album:info:")
    @GuiGuCached(prefix = "album:info:")
    public AlbumInfo getAlbumInfoById(Long id) {
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("albumInfo:bloomFilter");
        if (!bloomFilter.contains(id)) {
            throw new GuiguException(20001, "专辑不存在");
        }
        if(redisTemplate.opsForValue().getBit("albumInfo:bitmap", id)){
            System.out.println("该专辑存在");
        }
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);
        LambdaQueryWrapper<AlbumAttributeValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumAttributeValue::getAlbumId, id);
        albumInfo.setAlbumAttributeValueVoList(albumAttributeValueMapper.selectList(queryWrapper));

        return albumInfo;
    }

    /**
     * 修改专辑信息 涉及是否为公开状态即是否上架/下架专辑索引库
     *
     * @param id
     * @param userId
     * @param albumInfoVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @GuiGuCached(prefix = "album:info:1623", type = CacheOperationType.DELETE) // 修改时需要覆盖
    public void updateAlbumInfo(Long id, Long userId, AlbumInfoVo albumInfoVo) {
        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtil.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setId(id);
        albumInfo.setUserId(userId);
        // 获取专辑是否为公开状态
        AlbumInfo oldAlbumInfo = albumInfoMapper.selectById(id);
        String oldIsOpen = oldAlbumInfo.getIsOpen();
        String newIsOpen = albumInfoVo.getIsOpen();
        albumInfoMapper.updateById(albumInfo);

        // 判断修改前后是否为私密状态
        // 两次均为下架状态，则不需要二次处理
        if (oldIsOpen == "0" && newIsOpen.equals(oldIsOpen)) return;
        if (newIsOpen.equals("1")) {
            // 1 == 公开状态即上架专辑
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, id);
        } else {
            // 0 == 私密状态即下架专辑
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, id);
        }

        // 先删在更新
        LambdaQueryWrapper<AlbumAttributeValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumAttributeValue::getAlbumId, id);
        albumAttributeValueMapper.delete(queryWrapper);

        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        if (CollectionUtil.isNotEmpty(albumAttributeValueVoList)) {
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                albumAttributeValue.setAlbumId(id);
                albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
                albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAlbumInfoById(Long id) {
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();
        if (includeTrackCount > 0) {
            throw new GuiguException(400, "专辑下有声音，不能删除");
        }
        // 根据 albumId 删除专辑索引
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, id);
        albumInfoMapper.deleteById(id);
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, id));


    }

    @Override
    public List<AlbumInfo> listByuserId(Long userId) {
        LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumInfo::getUserId, userId);
        queryWrapper.orderBy(true, false, AlbumInfo::getId);
        queryWrapper.last("limit 100");
        return albumInfoMapper.selectList(queryWrapper);

    }

    @Override
    public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
         // 缓存Key
        String cacheKey = "test" + albumId;
        // 锁Key
        String lockKey = "lock:" + albumId;
        try {
            // 1. 先查缓存
            List<AlbumAttributeValue> cacheList = (List<AlbumAttributeValue>) redisTemplate.opsForValue().get(cacheKey);
            if (cacheList != null) {
                return cacheList;
            }

            // 2. 缓存未命中，使用固定锁Key redisson
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock();
                try {
                    // 3. 双重检查 避免其他线程重复重建
                    cacheList = (List<AlbumAttributeValue>) redisTemplate.opsForValue().get(cacheKey);
                    if (cacheList != null) {
                        return cacheList;
                    }

                    // 4. 查询数据库
                    List<AlbumAttributeValue> dbList = albumAttributeValueMapper.selectList(
                            new LambdaQueryWrapper<AlbumAttributeValue>()
                                    .eq(AlbumAttributeValue::getAlbumId, albumId));

                    if (CollectionUtil.isNotEmpty(dbList)) {
                        redisTemplate.opsForValue().set(cacheKey, dbList, 5, TimeUnit.MINUTES);
                        return dbList;
                    } else {
                        // 缓存空值并返回 防止缓存穿透
                        List<AlbumAttributeValue> emptyList = Collections.emptyList();
                        redisTemplate.opsForValue().set(cacheKey, emptyList, 1, TimeUnit.MINUTES);
                        return emptyList;
                    }
                } finally {
                    lock.unlock();
                }

        } catch (Exception e) {
            log.error("查询专辑属性异常", e);
            // 降级到数据库查询 兜底措施（避免前面出现异常无数据返回）
            return albumAttributeValueMapper.selectList(
                    new LambdaQueryWrapper<AlbumAttributeValue>()
                            .eq(AlbumAttributeValue::getAlbumId, albumId));
        }
    }

    /**
     * 测试 redisTemplate 、 redissonClient
     *
     * @param albumId
     * @return
     */

//    @Override
//    public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
//        // 缓存Key
//        String cacheKey = "test" + albumId;
//
//        try {
//            // 1. 先查缓存
//            List<AlbumAttributeValue> cacheList = (List<AlbumAttributeValue>) redisTemplate.opsForValue().get(cacheKey);
//            if (cacheList != null) {
//                return cacheList;
//            }
//
//            // 2. 缓存未命中，使用固定锁Key
//            String lockKey = "lock";
//            Boolean lockAcquired = redisTemplate.opsForValue()
//                    .setIfAbsent(lockKey, "locked", 5, TimeUnit.SECONDS);
//
//            if (Boolean.TRUE.equals(lockAcquired)) {
//                try {
//                    // 3. 双重检查 避免其他线程重复重建
//                    cacheList = (List<AlbumAttributeValue>) redisTemplate.opsForValue().get(cacheKey);
//                    if (cacheList != null) {
//                        return cacheList;
//                    }
//
//                    // 4. 查询数据库
//                    List<AlbumAttributeValue> dbList = albumAttributeValueMapper.selectList(
//                            new LambdaQueryWrapper<AlbumAttributeValue>()
//                                    .eq(AlbumAttributeValue::getAlbumId, albumId));
//
//                    if (CollectionUtil.isNotEmpty(dbList)) {
//                        redisTemplate.opsForValue().set(cacheKey, dbList, 5, TimeUnit.MINUTES);
//                        return dbList;
//                    } else {
//                        // 缓存空值并返回 防止缓存穿透
//                        List<AlbumAttributeValue> emptyList = Collections.emptyList();
//                        redisTemplate.opsForValue().set(cacheKey, emptyList, 1, TimeUnit.MINUTES);
//                        return emptyList;
//                    }
//                } finally {
//                    //4.1 先创建脚本对象 DefaultRedisScript泛型脚本语言返回值类型 Long 0：失败 1：成功
//                    DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//                    //4.2设置脚本文本
//                    String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
//                            "then\n" +
//                            "    return redis.call(\"del\",KEYS[1])\n" +
//                            "else\n" +
//                            "    return 0\n" +
//                            "end";
//                    redisScript.setScriptText(script);
//                    //4.3 设置响应类型
//                    redisScript.setResultType(Long.class);
//                    redisTemplate.execute(redisScript, Arrays.asList("lock"), "locked");
//                }
//            } else {
//                // 获取锁失败，短暂等待后重试
//                Thread.sleep(100);
//                return findAlbumAttributeValue(albumId); // 仍可递归，但建议改循环
//            }
//        } catch (Exception e) {
//            log.error("查询专辑属性异常", e);
//            // 降级到数据库查询 兜底措施（避免前面出现异常无数据返回）
//            return albumAttributeValueMapper.selectList(
//                    new LambdaQueryWrapper<AlbumAttributeValue>()
//                            .eq(AlbumAttributeValue::getAlbumId, albumId));
//        }
//    }


    /**
     * 根据专辑ID查询专辑统计信息
     *
     * @param albumId 专辑ID
     * @return
     */
    @Override
    //@GuiGuCache(prefix = "albumStatVo:")
    @GuiGuCached(prefix = "album:statvo:")
    public AlbumStatVo getAlbumStatVo(Long albumId) {
        return albumInfoMapper.getAlbumStatVo(albumId);
    }


}
